package com.example.easycharge.notRepEntity;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.LinkedList;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class WaitQueue {

    public static int MAX_QUEUE_SIZE = 2;

    @Schema(description = "充电桩编号")
    private long pileID;
    @Schema(description = "是否快充")
    private boolean isFast;
    @Schema(description = "充电桩提供的最大充电功率")
    private int chargePower;
    @Schema(description = "当前充电车辆")
    private ChargeRequest chargingVehicle;
    @Schema(description = "表示是否在充电")
    private boolean isCharge;
    /*
        free:空闲
        waitingDriveIn:等待驶入车位（但不确定是否是待充电车辆）
        waitingPlugIn:等待插入
        charging:充电中
        waitingPlugOff:等待拔出
        waitingDriveAway:等待驶离
        illegalOccupation:非法占用停车位
     */
    @Schema(description = "表示当前状态")
    private QueueStateEnum state;
    @Schema(description = "等待时间（等待插入/等待驶离/等待拔出/等待驶入）")
    private int waitMinutes;
    @Schema(description = "充满剩余时间")
    private int leftMinutes;
    @Schema(description = "等待车辆，不包含当前车辆")
    private LinkedList<ChargeRequest> chargeRequestLinkedList;
    @Schema(description = "队列等待长度")
    private int waitLength;
    @Schema(description = "总的等待时间")
    private int totalWaitTime;

    public void addNewVehicle(ChargeRequest chargeRequest, int chargeTime) {
        if (chargingVehicle == null) {
            chargingVehicle = chargeRequest;
            state = QueueStateEnum.WAITING_DRIVE_IN;
        } else {
            chargeRequestLinkedList.add(chargeRequest);
            waitLength++;
        }
        totalWaitTime += chargeTime;
    }

    // 充电车辆取消充电，更改队列状态
    public void cancelChargeState() {
        isCharge = false;
        if (state == QueueStateEnum.WAITING_DRIVE_IN) {
            if (waitLength == 0) {
                state = QueueStateEnum.FREE;
            }
        } else if (state == QueueStateEnum.WAITING_PLUG_IN) {
            state = QueueStateEnum.WAITING_DRIVE_AWAY;
        } else if (state == QueueStateEnum.CHARGING) {
            state = QueueStateEnum.WAITING_PLUG_OFF;
        }
    }

    // 充电车辆取消充电，更改队列等待时间（包含等待车辆）
    public void cancelChargeTime() {
        waitMinutes = 0;
        int chargeLeftTime = leftMinutes;
        leftMinutes = 0;
        totalWaitTime -= chargingVehicle.getEstimateChargeTime();
        chargingVehicle.setEstimateChargeTime(0);
        if (waitLength != 0) {
            for (ChargeRequest chargeRequest : chargeRequestLinkedList) {
                chargeRequest.setEstimateWaitTime(chargeRequest.getEstimateChargeTime() - chargeLeftTime);
            }
        }
    }

    // 重新估计剩下车辆的等待时间
    public void reEsTime() {
        int chargeTime = chargingVehicle.getEstimateChargeTime();
        for (ChargeRequest chargeRequest : chargeRequestLinkedList) {
            chargeRequest.setEstimateWaitTime(chargeRequest.getEstimateChargeTime() - chargeTime);
        }
    }

    // 将下一辆车开始充电
    public void nextVehicle() {
        chargingVehicle = chargeRequestLinkedList.pollFirst();
        if (chargingVehicle == null) {
            return;
        }
        waitMinutes = 0;
        leftMinutes = chargingVehicle.getEstimateChargeTime();
        // 将状态设置为等待车辆驶入
        state = QueueStateEnum.WAITING_DRIVE_IN;
        waitLength--;
    }

    // 对'非'队头的车辆执行取消充电操作
    public boolean removeVehicle(long vehicleId) {
        boolean hasFind = false;
        int cancelChargeTime = 0;
        ChargeRequest needRemovedRequest = null;
        for (ChargeRequest chargeRequest : chargeRequestLinkedList) {
            if (hasFind) {
                // 将后方车辆的等待时间减去取消充电的车辆的预计充电时间
                chargeRequest.setEstimateWaitTime(chargeRequest.getEstimateChargeTime() - cancelChargeTime);
            }
            if (!hasFind && chargeRequest.getVehicleId() == vehicleId) {
                needRemovedRequest = chargeRequest;
                // 减去取消的车辆预计的等待时间
                cancelChargeTime = chargeRequest.getEstimateChargeTime();
                totalWaitTime -= cancelChargeTime;
                waitLength--;
                hasFind = true;
            }
        }
        if (hasFind)
            chargeRequestLinkedList.remove(needRemovedRequest);
        return hasFind;
    }

    // 充满电
    public void finishCharge() {
        isCharge = false;
        state = QueueStateEnum.WAITING_PLUG_OFF;
    }

    // 通过车辆编号获取充电请求信息
    public ChargeRequest getRequestById(long vehicleId) {
        if (chargingVehicle.getVehicleId() == vehicleId) {
            return chargingVehicle;
        }
        for (ChargeRequest chargeRequest : chargeRequestLinkedList) {
            if (chargeRequest.getVehicleId() == vehicleId) {
                return chargeRequest;
            }
        }
        return null;
    }

    public void unplug() {
        state = QueueStateEnum.WAITING_DRIVE_AWAY;
        isCharge = false;
        waitMinutes = 0;
    }

    public void startCharge() {
        leftMinutes = chargingVehicle.getEstimateChargeTime();
        state = QueueStateEnum.CHARGING;
        isCharge = true;
        waitMinutes = 0;
    }

    public void minutesTick() {
        leftMinutes--;
        totalWaitTime--;
        chargingVehicle.increasePower();
    }

    public void waitTick() {
        waitMinutes++;
    }

    public void driveIn(long vehicleId) {
        if (chargingVehicle.getVehicleId() == vehicleId) {
            state = QueueStateEnum.WAITING_PLUG_IN;
            waitMinutes = 0;
        } else {
            state = QueueStateEnum.ILLEGAL_OCCUPATION;
        }
    }

    public void driveAway() {
        waitMinutes = 0;
        if (state == QueueStateEnum.ILLEGAL_OCCUPATION) {
            if (chargingVehicle == null) {
                state = QueueStateEnum.FREE;
            } else {
                state = QueueStateEnum.WAITING_DRIVE_IN;
            }
        } else if (state == QueueStateEnum.WAITING_PLUG_IN) {
            if (waitLength == 0) {
                chargingVehicle = null;
                state = QueueStateEnum.FREE;
                totalWaitTime = 0;
            }
        } else if (state == QueueStateEnum.WAITING_DRIVE_AWAY) {
            if (waitLength == 0) {
                chargingVehicle = null;
                state = QueueStateEnum.FREE;
                leftMinutes = 0;
                totalWaitTime = 0;
            } else {
                state = QueueStateEnum.WAITING_DRIVE_IN;
            }
        }

    }

    public WaitQueue(long pileID, int chargePower, boolean isFast) {
        this.isFast = isFast;
        this.pileID = pileID;
        this.chargePower = chargePower;
        this.state = QueueStateEnum.FREE;
        this.chargingVehicle = null;
        this.totalWaitTime = 0;
        this.waitMinutes = 0;
        this.waitLength = 0;
        this.chargeRequestLinkedList = new LinkedList<>();
    }

    public LinkedList<ChargeRequest> removeWaitVehicle() {
        waitLength = 0;
        waitMinutes = chargingVehicle.getEstimateChargeTime();
        LinkedList<ChargeRequest> result = new LinkedList<>(chargeRequestLinkedList);
        chargeRequestLinkedList.clear();
        return result;
    }

    public boolean isFull() {
        return waitLength >= MAX_QUEUE_SIZE;
    }
}
